<?php

declare(strict_types=1);

namespace App\Controller\AdminApi;

use App\Exception\XZXValidationException;
use App\Middleware\AdminApi\AdminJWTAuthMiddleware;
use App\Middleware\AdminApi\NodeAccessMiddleware;
use App\Service\StatMonthlyTradeService;
use App\Service\SysExportLogService;
use App\Utils\CustomUtils;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Logger\LoggerFactory;
use Hyperf\Validation\Contract\ValidatorFactoryInterface;

/**
 * Class StatMonthlyTradeController
 * @package App\Controller
 * @Controller(prefix="/admin/api/statMonthlyTrade")
 */
class StatMonthlyTradeController extends AdminBaseController
{
    /**
     * @Inject()
     * @var ValidatorFactoryInterface
     */
    protected $validationFactory;

    /**
     * @Inject()
     * @var StatMonthlyTradeService
     */
    protected $StatMonthlyTradeService;

    /**
     * @Inject()
     * @var SysExportLogService
     */
    protected $SysExportLogService;

    /**
     * @var \Psr\Log\LoggerInterface
     */
    protected $logger;

    public function __construct(LoggerFactory $loggerFactory)
    {
        // 第一个参数对应日志的 name, 第二个参数对应 config/autoload/logger.php 内的 key
        $this->logger = $loggerFactory->get('log', 'default');
    }

    /**
     * 查询
     * @PostMapping(path = "statList")
     * @Middlewares({
     *     @Middleware(AdminJWTAuthMiddleware::class),
     *     @Middleware(NodeAccessMiddleware::class)
     * })
     */
    public function statList(RequestInterface $request)
    {

        $validator = $this->validationFactory->make(
            $request->all(),
            [
                'page'  => 'required|integer|min:1',
                'limit' => 'required|integer|min:1',
            ]
        );

        if ($validator->fails()){
            // Handle exception
            $errorMessage = $validator->errors()->first();  
            throw new XZXValidationException($errorMessage);
        }
        
        $param = $request->all();

        if(isset($param['search'])){
            $search = $param['search'];
            CustomUtils::xzxAddSearch($param, $search, 'channelName');
            CustomUtils::xzxAddSearch($param, $search, 'mchName');
            CustomUtils::xzxAddSearch($param, $search, 'mchNo');
            CustomUtils::xzxAddSearch($param, $search, 'type');
            CustomUtils::xzxAddSearch($param, $search, 'statMonth');
            if(isset($param["statMonth"]))
            {
                if (!empty($param["statMonth"])) {
                    $param['statMonth'][0] = $param['statMonth'][0];
                    $param['statMonth'][1] = $param['statMonth'][1];
                } else {
                    unset($param['statMonth']);
                }
            }
        }

        $ext = $this->request->getAttribute("ext");;
        $params['source']      = 2;
        $params['isSuperRole'] = $ext['isSuperRole'];
        if (!$params['isSuperRole']) {
            $params['mchIdList'] = $ext['mchIdList'];
        }

        if ($param['type'] == 'mch') {
            return $this->StatMonthlyTradeService->statMchList($param);
        } else {
            return $this->StatMonthlyTradeService->statChannelList($param);
        }

    }

    /**
     * 查询
     * @PostMapping(path = "financeList")
     * @Middlewares({
     *     @Middleware(AdminJWTAuthMiddleware::class),
     *     @Middleware(NodeAccessMiddleware::class)
     * })
     */
    public function financeList(RequestInterface $request)
    {

        $validator = $this->validationFactory->make(
            $request->all(),
            [
                'page'  => 'required|integer|min:1',
                'limit' => 'required|integer|min:1',
            ]
        );

        if ($validator->fails()){
            // Handle exception
            $errorMessage = $validator->errors()->first();
            throw new XZXValidationException($errorMessage);
        }

        $param = $request->all();

        if(isset($param['search'])){
            $search = $param['search'];
            CustomUtils::xzxAddSearch($param, $search, 'channelName');
            CustomUtils::xzxAddSearch($param, $search, 'mchName');
            CustomUtils::xzxAddSearch($param, $search, 'mchNo');
            CustomUtils::xzxAddSearch($param, $search, 'type');
            CustomUtils::xzxAddSearch($param, $search, 'statMonth');
            if(isset($param["statMonth"]))
            {
                if (!empty($param["statMonth"])) {
                    $param['statMonth'][0] = $param['statMonth'][0];
                    $param['statMonth'][1] = $param['statMonth'][1];
                } else {
                    unset($param['statMonth']);
                }
            }
        }

        if ($param['type'] == 'mch') {
            return $this->StatMonthlyTradeService->financeMchList($param);
        } else {
            return $this->StatMonthlyTradeService->financeChannelList($param);
        }
    }

    /**
     * 设置渠道费用
     * @PostMapping(path = "setChannelSettleAmount")
     * @Middlewares({
     *     @Middleware(AdminJWTAuthMiddleware::class),
     *     @Middleware(NodeAccessMiddleware::class)
     * })
     */
    public function setChannelSettleAmount(RequestInterface $request)
    {

        $validator = $this->validationFactory->make(
            $request->all(),
            [
                'settleAmount'  => 'required|integer|min:0',
            ]
        );

        if ($validator->fails()){
            // Handle exception
            $errorMessage = $validator->errors()->first();
            throw new XZXValidationException($errorMessage);
        }

        $param = $request->all();
        return $this->StatMonthlyTradeService->setChannelSettleAmount($param);
    }

    /**
     * 查询
     * @PostMapping(path = "getTradeChannelList")
     * @Middlewares({
     *     @Middleware(AdminJWTAuthMiddleware::class),
     *     @Middleware(NodeAccessMiddleware::class)
     * })
     */
    public function getTradeChannelList(RequestInterface $request)
    {

        $validator = $this->validationFactory->make(
            $request->all(),
            [
                'page'  => 'required|integer|min:1',
                'limit' => 'required|integer|min:1',
            ]
        );

        if ($validator->fails()){
            // Handle exception
            $errorMessage = $validator->errors()->first();
            throw new XZXValidationException($errorMessage);
        }

        $param = $request->all();

        if(isset($param['search'])){
            $search = $param['search'];
            CustomUtils::xzxAddSearch($param, $search, 'channelId');
            CustomUtils::xzxAddSearch($param, $search, 'statMonth');
        }

        return $this->StatMonthlyTradeService->getTradeChannelList($param);

    }

    /**
     * 币种转换，损益计算
     * @PostMapping(path = "currencyTrans")
     * @Middlewares({
     *     @Middleware(AdminJWTAuthMiddleware::class),
     *     @Middleware(NodeAccessMiddleware::class)
     * })
     */
    public function currencyTrans(RequestInterface $request)
    {

        $validator = $this->validationFactory->make(
            $request->all(),
            [
                'id'    => 'required|uuid',
                'data'  => 'required|array',
            ]
        );

        if ($validator->fails()){
            // Handle exception
            $errorMessage = $validator->errors()->first();
            throw new XZXValidationException($errorMessage);
        }

        $param = $request->all();
        return $this->StatMonthlyTradeService->currencyTrans($param);

    }

    /**
     * 导出
     * @PostMapping(path = "statExportExcel")
     * @Middleware(AdminJWTAuthMiddleware::class)
     * @param RequestInterface $request
     * @return array|mixed
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \Throwable
     * @throws \TypeError
     */
    public function statExportExcel(RequestInterface $request) {

        $param = $request->all();

        $type = 5;

        // 新增导出记录
        $ext = $this->request->getAttribute("ext");
        $result = $this->SysExportLogService->add(['type' => $type, 'createBy'=>$ext['createBy']]);


        // 直接把页数拖到很大
        $param['page'] = $request->post('page', 1);
        $param['limit'] = 10000000;

        if(isset($param['search'])){
            $search = $param['search'];
            CustomUtils::xzxAddSearch($param, $search, 'channelName');
            CustomUtils::xzxAddSearch($param, $search, 'mchName');
            CustomUtils::xzxAddSearch($param, $search, 'mchNo');
            CustomUtils::xzxAddSearch($param, $search, 'type');
            CustomUtils::xzxAddSearch($param, $search, 'statMonth');
            if(isset($search["statMonth"]))
            {
                if (!empty($search["statMonth"])) {
                    $param['statMonth'][0] = $param['statMonth'][0];
                    $param['statMonth'][1] = $param['statMonth'][1];
                } else {
                    unset($param['statMonth']);
                }
            }
        }

        $logId = $result['data'];
        $fileName = 'stat-' . $param['type'] . '-' . date('YmdHis') . rand(1000, 9999);
        if ($param['type'] == 'mch') {
            // 商户维度的统计
            $xlsCell = [
                ['filed' => 'statMonth',                    'name'  => '统计月份'],
                ['filed' => 'mchNo',                        'name'  => '商户号'],
                ['filed' => 'mchName',                      'name'  => '商户名称'],
                ['filed' => 'successCount',                 'name'  => '交易成功订单数'],
                ['filed' => 'totalCount',                   'name'  => '尝试交易订单数'],
                ['filed' => 'refundCount',                  'name'  => '退款订单数'],
                ['filed' => 'disCount',                     'name'  => '拒付订单数'],
                ['filed' => 'riskCount',                    'name'  => '风控阻挡单数'],
                ['filed' => 'floatSuccessRate',             'name'  => '成功率'],
                ['filed' => 'floatRefundRate',              'name'  => '退款率'],
                ['filed' => 'floatDisRate',                 'name'  => '拒付率'],
            ];
        } else {
            // 渠道维度的统计
            $xlsCell = [
                ['filed' => 'statMonth',                    'name'  => '统计月份'],
                ['filed' => 'channelNo',                    'name'  => '渠道号'],
                ['filed' => 'channelName',                  'name'  => '渠道名称'],
                ['filed' => 'successCount',                 'name'  => '交易成功订单数'],
                ['filed' => 'totalCount',                   'name'  => '尝试交易订单数'],
                ['filed' => 'refundCount',                  'name'  => '退款订单数'],
                ['filed' => 'disCount',                     'name'  => '拒付订单数'],
                ['filed' => 'floatSuccessRate',             'name'  => '成功率'],
                ['filed' => 'floatRefundRate',              'name'  => '退款率'],
                ['filed' => 'floatDisRate',                 'name'  => '拒付率'],
            ];
        }

        $this->SysExportLogService->addToTask([
            'logId'     => $logId,
            'fileName'  => $fileName,
            'type'      => $type,
            'param'     => $param,
            'xlsCell'   => $xlsCell
        ]);

        return $result;
    }

    /**
     * 导出
     * @PostMapping(path = "financeExportExcel")
     * @Middleware(AdminJWTAuthMiddleware::class)
     * @param RequestInterface $request
     * @return array|mixed
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \Throwable
     * @throws \TypeError
     */
    public function financeExportExcel(RequestInterface $request) {
        $param = $request->all();

        $type = 4;

        // 新增导出记录
        $ext = $this->request->getAttribute("ext");
        $result = $this->SysExportLogService->add(['type' => $type, 'createBy' => $ext['createBy']]);


        // 直接把页数拖到很大
        $param['page'] = $request->post('page', 1);
        $param['limit'] = 10000000;

        if(isset($param['search'])){
            $search = $param['search'];
            CustomUtils::xzxAddSearch($param, $search, 'channelName');
            CustomUtils::xzxAddSearch($param, $search, 'mchName');
            CustomUtils::xzxAddSearch($param, $search, 'mchNo');
            CustomUtils::xzxAddSearch($param, $search, 'type');
            CustomUtils::xzxAddSearch($param, $search, 'statMonth');
            if(isset($search["statMonth"]))
            {
                if (!empty($search["statMonth"])) {
                    $param['statMonth'][0] = $param['statMonth'][0];
                    $param['statMonth'][1] = $param['statMonth'][1];
                } else {
                    unset($param['statMonth']);
                }
            }
        }

        $logId = $result['data'];
        $fileName = 'finance-' . $param['type'] . '-' . date('YmdHis') . rand(1000, 9999);
        if ($param['type'] == 'mch') {
            // 商户维度的统计
            $xlsCell = [
                ['filed' => 'statMonth',                    'name'  => '统计月份'],
                ['filed' => 'mchNo',                        'name'  => '商户号'],
                ['filed' => 'mchName',                      'name'  => '商户名称'],
                ['filed' => 'floatSettleAmount',            'name'  => '商户尝试交易结算金额'],
                ['filed' => 'floatSuccessSettleAmount',     'name'  => '商户成功交易结算金额'],
                ['filed' => 'floatDisSettleAmount',         'name'  => '拒付结算金额'],
                ['filed' => 'floatRefundSettleAmount',      'name'  => '退款结算金额'],

                ['filed' => 'floatServiceFee',              'name'  => '交易手续费'],
                ['filed' => 'floatPerFee',                  'name'  => '单笔手续费'],
                ['filed' => 'floatFrozenSettleAmount',      'name'  => '冻结结算金额'],
                ['filed' => 'floatThawSettleAmount',        'name'  => '解冻结算金额'],
                ['filed' => 'floatBondAmount',              'name'  => '平台保证金'],
                ['filed' => 'floatWithdrawFee',             'name'  => '提现手续费'],
                ['filed' => 'floatTransFee',                'name'  => '转账手续费'],
                ['filed' => 'floatRefundFee',               'name'  => '单笔退款手续费'],
                ['filed' => 'floatDisFee',                  'name'  => '拒付处理费'],
                ['filed' => 'floatDisLookIntoFee',          'name'  => '拒付调查费'],
                ['filed' => 'floatThreeDJudgeFee',          'name'  => '3D判定费'],
                ['filed' => 'floatThreeDFee',               'name'  => '3D手续费'],
                ['filed' => 'floatSalesCommission',         'name'  => '销售提成'],
                ['filed' => 'floatEventFreezeAmount',       'name'  => '事件冻结金额'],
                ['filed' => 'floatEventThawAmount',         'name'  => '事件解冻金额'],
                ['filed' => 'floatEventDeductionAmount',    'name'  => '事件扣款金额'],
                ['filed' => 'floatEventRechargeAmount',     'name'  => '事件重置金额'],
            ];
        } else {
            // 渠道维度的统计
            $xlsCell = [
                ['filed' => 'statMonth',                            'name'  => '统计月份'],
                ['filed' => 'channelNo',                            'name'  => '渠道号'],
                ['filed' => 'channelName',                          'name'  => '渠道名称'],
                ['filed' => 'settleCurrency',                       'name'  => '结算币种'],
                ['filed' => 'floatSettleAmount',                    'name'  => '结算金额'],
                ['filed' => 'floatServiceFeeRate',                  'name'  => '交易手续费率'],
                ['filed' => 'floatCurrencyTransMchSettleAmount',    'name'  => '商户转换结算金额'],
                ['filed' => 'floatCurrencyTransSalesCommission',    'name'  => '总销售分润'],
                ['filed' => 'floatCurrencyTransSalesCommission1',   'name'  => '一级分润'],
                ['filed' => 'floatCurrencyTransSalesCommission2',   'name'  => '二级分润'],
                ['filed' => 'floatProfit',                          'name'  => '利润'],
            ];
        }

        $this->SysExportLogService->addToTask([
            'logId'     => $logId,
            'fileName'  => $fileName,
            'type'      => $type,
            'param'     => $param,
            'xlsCell'   => $xlsCell
        ]);

        return $result;
    }
   
}